package deepbrain.simnetwork.loader.vertex;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import deepbrain.simnetwork.exception.SimNetworkException;
import deepbrain.simnetwork.exception.SimNetworkRuntimeException;
import deepbrain.simnetwork.mechanism.Mechanism;
import deepbrain.simnetwork.mechanism.MechanismProperties;

public class XmlVertexesLoader implements VertexesLoader {

	private Document document;

	public XmlVertexesLoader(String filePath) throws SimNetworkException {
		try {
			InputStream inputStream = new FileInputStream(filePath);
			loadDocument(inputStream);
		} catch (FileNotFoundException e) {
			throw new SimNetworkException("Cannot Open File:" + filePath
					+ " When Loading Vertexes", e);
		}
	}

	public XmlVertexesLoader(InputStream inputStream)
			throws SimNetworkException {
		loadDocument(inputStream);
	}

	private void loadDocument(InputStream inputStream)
			throws SimNetworkException {
		SAXReader reader = new SAXReader();
		try {
			document = reader.read(inputStream);
		} catch (DocumentException e) {
			throw new SimNetworkException(
					"Cannot Parse Matrix XML When Loading Vertexes", e);
		}
	}

	public List<VertexInformation> loadVertexes() {
		if (document == null)
			return null;
		List<VertexInformation> vertexes = new ArrayList<VertexInformation>();
		HashMap<String, String> mechanismMap = new HashMap<String, String>();

		List<?> mechanisms = document.selectNodes("//network/mechanism");
		for (Object _mechanism : mechanisms) {
			Element mechanism = (Element) _mechanism;
			mechanismMap.put(mechanism.elementTextTrim("name"), mechanism
					.elementTextTrim("class"));
		}

		List<?> vertexElements = document.selectNodes("//network/vertex/node");
		for (Object _vertex : vertexElements) {
			Element vertex = (Element) _vertex;
			VertexInformation vertexInfo = new VertexInformation();
			int no = Integer.parseInt(vertex.attributeValue("no").trim());
			vertexInfo.setNodeNo(no);
			String mechanismStr = vertex.elementTextTrim("mechanism");
			Mechanism mechanism = null;
			try {
				mechanism = (Mechanism) Class.forName(
						mechanismMap.get(mechanismStr)).newInstance();
			} catch (Exception e) {
				throw new SimNetworkRuntimeException(e);
			}
			vertexInfo.setMechanism(mechanism);
			
			List<?> mechanismPropertiess = vertex.elements("mechanism-property");
			
			MechanismProperties mechanismProperties = new MechanismProperties();
			for(Object o:mechanismPropertiess) {
				Element _mechanismProperties = (Element)o;
				String name = _mechanismProperties.elementTextTrim("name");
				String value = _mechanismProperties.elementTextTrim("value");
				mechanismProperties.setProperty(name, value);
			}
			
			vertexInfo.setMechanismProperties(mechanismProperties);
			
			String afferentsStr = vertex.elementTextTrim("afferents");
			String[] afferents = afferentsStr.split(" ");
			for (String afferent : afferents) {
				try {
					vertexInfo.addAfferentNodes(Integer.parseInt(afferent
							.trim()));
				} catch (Exception e) {
				}
			}
			vertexes.add(vertexInfo);
		}

		return vertexes;
	}

}
